﻿////////////////////////////////////////////////////////////////
///
/// File: BodyToken.cs
/// Author: Lucio Davide Spano
/// Last update: 27 July 2012
/// Description: This class represents the token used 
///              by the multitouch platform during the temporal
///              expression execution
/// To do: 
/// ------------------------------------------------------------
/// Copyright (c) 2012 Lucio Davide Spano 
///                     (lucio.davide.spano@isti.cnr.it)
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------
////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using GestIT;
namespace TouchGestIT
{
    public class TouchToken : Token
    {
        public PointTracking Tracking { get; private set; }

        private List<TouchPoint>[] touches;
        private int touchCount;

        public TouchToken(PointTracking tracking)
            : this(tracking, 10)
        {
            
        }

        public TouchToken(PointTracking tracking, int touchCount)
            : base()
        {
            this.Tracking = tracking;
            this.touchCount = touchCount;

            touches = new List<TouchPoint>[this.touchCount];
            for (int i = 0; i < touches.Length; i++)
            {


                switch (Tracking)
                {
                    case PointTracking.Last:
                        {
                            touches[i] = new List<TouchPoint>(1);
                            touches[i].Add(new TouchPoint());
                        } break;

                    case PointTracking.Path:
                        {
                            touches[i] = new List<TouchPoint>();
                        } break;

                    case PointTracking.Previous:
                        {
                            touches[i] = new List<TouchPoint>(2);
                            touches[i].Add(new TouchPoint());
                            touches[i].Add(new TouchPoint());
                        } break;

                    case PointTracking.StartLast:
                        {
                            touches[i] = new List<TouchPoint>(2);
                            touches[i].Add(new TouchPoint());
                            touches[i].Add(new TouchPoint());
                        } break;

                    case PointTracking.StartPrevious:
                        {
                            touches[i] = new List<TouchPoint>(3);
                            touches[i].Add(new TouchPoint());
                            touches[i].Add(new TouchPoint());
                            touches[i].Add(new TouchPoint());
                        } break;
                }
            }
        }

        public void Save(TouchEventArgs args)
        {
            if (args.Id < 0 || args.Id >= touches.Length)
            {
                return;
            }

            int tid = args.Id;

            switch (Tracking)
            {
                case PointTracking.Last:
                    {
                        touches[tid][0].X = args.Point.X;
                        touches[tid][0].Y = args.Point.Y;
                    }break;

                case PointTracking.Path:
                    {
                        touches[tid].Add(new TouchPoint(args.Point.X, args.Point.Y));
                    }break;

                case PointTracking.Previous:
                    {
                        touches[tid][0].X = touches[tid][1].X;
                        touches[tid][0].Y = touches[tid][1].Y;

                        touches[tid][1].X = args.Point.X;
                        touches[tid][1].Y = args.Point.Y;
                    }break;

                case PointTracking.StartLast:
                    {
                        if (args.Type == TouchType.Start)
                        {
                            touches[tid][0].X = args.Point.X;
                            touches[tid][0].Y = args.Point.Y;
                        }

                        touches[tid][1].X = args.Point.X;
                        touches[tid][1].Y = args.Point.Y;
                    }break;

                case PointTracking.StartPrevious:
                    {
                        if (args.Type == TouchType.Start)
                        {
                            touches[tid][0].X = args.Point.X;
                            touches[tid][0].Y = args.Point.Y;
                        }

                        touches[tid][1].X = touches[tid][2].X;
                        touches[tid][1].Y = touches[tid][2].Y;

                        touches[tid][2].X = args.Point.X;
                        touches[tid][2].Y = args.Point.Y;
                    }break;
            }
        }

        public TouchPoint GetPosition(int touchId)
        {
            if (touchId < 0 || touchId >= touches.Length)
            {
                return TouchPoint.ErrorPoint;
            }

            switch (Tracking)
            {
                case PointTracking.Last:
                    {
                        return touches[touchId][0];
                    }

                case PointTracking.StartLast: goto case PointTracking.Previous;
                case PointTracking.Previous:
                    {
                        return touches[touchId][1];
                    }

                case PointTracking.StartPrevious:
                    {
                        return touches[touchId][2];
                    }

                case PointTracking.Path:
                    {
                        if (touches[touchId].Count == 0)
                        {
                            return TouchPoint.ErrorPoint;
                        }
                        else
                        {
                            return touches[touchId][touches[touchId].Count - 1];
                        }
                    }

                default:
                    {
                        return TouchPoint.ErrorPoint;
                    }
            }
        }

        public TouchPoint GetPreviousPosition(int touchId)
        {
            if (touchId < 0 || touchId >= touches.Length)
            {
                return TouchPoint.ErrorPoint;
            }

            switch (Tracking)
            {
                case PointTracking.Previous:
                    {
                        return touches[touchId][0];
                    }

                case PointTracking.StartPrevious:
                    {
                        return touches[touchId][1];
                    }

                case PointTracking.Path:
                    {
                        if (touches[touchId].Count <= 1)
                        {
                            return TouchPoint.ErrorPoint;
                        }
                        else
                        {
                            return touches[touchId][touches[touchId].Count - 2];
                        }
                    }

                default:
                    {
                        return TouchPoint.ErrorPoint;
                    }
            }
        }

        public TouchPoint GetStartPosition(int touchId)
        {
            if (touchId < 0 || touchId >= touches.Length)
            {
                return TouchPoint.ErrorPoint;
            }

            switch (Tracking)
            {
                case PointTracking.StartLast: goto case PointTracking.StartPrevious;
                case PointTracking.StartPrevious:
                    return touches[touchId][0];
                case PointTracking.Path:
                    if (touches[touchId].Count == 0)
                    {
                        return TouchPoint.ErrorPoint;
                    }
                    else
                    {
                        return touches[touchId][0];
                    }
                default:
                    return TouchPoint.ErrorPoint;
            }
        }

        public TouchPoint GetPositionAtTime(int touchId, int i)
        {
            if (touchId < 0 || touchId >= touches.Length)
            {
                return TouchPoint.ErrorPoint;
            }

            if (Tracking != PointTracking.Path)
            {
                return TouchPoint.ErrorPoint;
            }

            if (i < 0 || i >= touches[touchId].Count)
            {
                return TouchPoint.ErrorPoint;
            }

            return touches[touchId][i];
        }

        public int GetPathLength(int touchId)
        {
            if (touchId < 0 || touchId >= touches.Length)
            {
                return -1;
            }

            if (Tracking != PointTracking.Path)
            {
                return -1;
            }

            return touches[touchId].Count;
        }
           
    }

    public enum PointTracking
    {
        Last,
        Previous,
        Path,
        StartLast,
        StartPrevious
    }
}
